package com.health.ts.utils;

import org.springframework.beans.BeansException;
import org.springframework.beans.factory.support.BeanDefinitionBuilder;
import org.springframework.beans.factory.support.DefaultListableBeanFactory;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.context.ConfigurableApplicationContext;

/**
 * Description {spring ApplicationContext管理工具}
 */
public class ApplicationContextUtil implements ApplicationContextAware {
	
	/**
	 * ApplicationContext
	 */
	private static ApplicationContext applicationContext;

	@Override
	public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
		ApplicationContextUtil.applicationContext = applicationContext;
	}

	/**
	 * @param name
	 * @return
	 */
	public static Object getBean(String name) throws BeansException {
		return applicationContext.getBean(name);
	}

	/**
	 * @param name
	 * @param requiredType
	 * @return
	 * @throws BeansException
	 */
	public static <T> T getBean(String name, Class<T> requiredType) throws BeansException {
		return applicationContext.getBean(name, requiredType);
	}

	/**
	 * @param requiredType
	 * @return
	 * @throws BeansException
	 */
	public static <T> T getBean(Class<T> requiredType) throws BeansException {
		return applicationContext.getBean(requiredType);
	}

	/**
	 * @param name
	 * @return
	 */
	public static boolean containsBean(String name) {
		return applicationContext.containsBean(name);
	}
	
	/**
	 * 注册bean到spring容器中
	 *
	 * @param beanName 名称
	 * @param clazz    bean类型
	 * @param args     构造方法参数
	 */
	public static void registerBean(String beanName, Class<?> clazz, Object... args) {
		// 将applicationContext转换为ConfigurableApplicationContext
		ConfigurableApplicationContext configurableApplicationContext = (ConfigurableApplicationContext) applicationContext;
		// 获取bean工厂并转换为DefaultListableBeanFactory
		DefaultListableBeanFactory defaultListableBeanFactory = (DefaultListableBeanFactory) configurableApplicationContext.getBeanFactory();
		// 通过BeanDefinitionBuilder创建bean定义
		BeanDefinitionBuilder beanDefinitionBuilder = BeanDefinitionBuilder.genericBeanDefinition(clazz);
		// 尝试移除之前相同的bean
		if (defaultListableBeanFactory.containsBean(beanName)) {
			defaultListableBeanFactory.removeBeanDefinition(beanName);
		}
		for (Object arg : args) {
			beanDefinitionBuilder.addConstructorArgValue(arg);
		}
		// 注册bean
		defaultListableBeanFactory.registerBeanDefinition(beanName, beanDefinitionBuilder.getRawBeanDefinition());
	}

	/**
	 * 注册bean到spring容器中
	 *
	 * @param beanName 名称
	 * @param bean     bean 实例
	 */
	public static <T> void registerBean(String beanName, T bean) {
		// 将applicationContext转换为ConfigurableApplicationContext
		ConfigurableApplicationContext configurableApplicationContext = (ConfigurableApplicationContext) applicationContext;
		// 获取bean工厂并转换为DefaultListableBeanFactory
		DefaultListableBeanFactory defaultListableBeanFactory = (DefaultListableBeanFactory) configurableApplicationContext.getBeanFactory();
		// 尝试移除之前相同的bean
		if (defaultListableBeanFactory.containsBean(beanName)) {
			defaultListableBeanFactory.removeBeanDefinition(beanName);
		}
		// 注册bean
		defaultListableBeanFactory.registerSingleton(beanName, bean);
	}
}
